﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UIWindow.Domains;
using UIWindow.Enums;
using UIWindow.GlobalParameters;
using UIWindow.Models;

namespace UIWindow.Helper
{
    public static class ValueConversions
    {
        public static T UpdateValue<T>(this T t, T obj)
        {
            var objProper = obj.GetType().GetProperties();
            foreach (var item in t.GetType().GetProperties())
            {
                objProper.Where(x => x.Name == item.Name).FirstOrDefault().SetValue(obj, item.GetValue(t, null));
            }
            return obj;
        }

        /// <summary>
        /// 检测当前时间是否是年份交换或季节交换节点
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static bool ContrastTime(this DateTime dateTime) => (dateTime.Month == 1 || dateTime.Month == 4 || dateTime.Month == 7 || dateTime.Month == 10);

        /// <summary>
        /// 计算季度===三个月为一季
        /// </summary>
        /// <param name="count">当前时间</param>
        /// <returns>1 = 1-3月；2 = 4-6月；3 = 7-9月；4 = 10-12月</returns>
        public static int GetQuarterly(this DateTime dateTime)
        {
            return dateTime.Month switch
            {
                int p when p >= 1 && p < 4 => 1,
                int p when p >= 4 && p < 7 => 2,
                int p when p >= 7 && p < 10 => 3,
                int p when p >= 10 && p <= 12 => 4,
                _ => 1,
            };
        }

        /// <summary>
        /// 获取称重重量
        /// </summary>
        /// <param name="originalbyte">称重数据</param>
        /// <returns>值不正确为0</returns>
        public static double? GetWeighingWeight(this byte[] originalbyte)
        {
            if (originalbyte != null && originalbyte.Length >= 18)
            {
                byte[] bytes = new byte[0];
                if (originalbyte.Length == 20) bytes = originalbyte;
                if (originalbyte.Length < 20) return 0;
                if (originalbyte.Length > 20)
                {
                    var str = Encoding.ASCII.GetString(originalbyte).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    if (str.Length > 1)
                    {
                        int count = 0;
                        for (int i = str.Length - 1; i > 0; i--)
                        {
                            if (str[i].Length == 18 
                                && !str[i].Contains("AL--1") 
                                && str[i].Contains("ST,GS"))
                            {
                                count = i;
                                break;
                            }
                        }
                        bytes = Encoding.ASCII.GetBytes(str[count]);
                    }
                    else
                    {
                        bytes = Encoding.ASCII.GetBytes(str[0]);
                        if (bytes.Length < 18) return null;
                    }
                }
                if (bytes.Length != 18) return null;
                var section1 = Encoding.ASCII.GetString(bytes, 0, 2);//ST
                var section2 = Encoding.ASCII.GetString(bytes, 3, 2);//GS
                var section3 = Encoding.ASCII.GetString(bytes, 6, 1);//+
                var section4 = Encoding.ASCII.GetString(bytes, 7, 7);//value
                double.TryParse(section4, out double w);
                if (section1.ToUpper() == "ST" && !section3.Contains("-")) return w;
            }
            return null;
        }

        /// <summary>
        /// AND AD 4531B型号电子秤解析
        /// </summary>
        /// <param name="originalbyte"></param>
        /// <returns></returns>
        public static double? GetAndWeight(this byte[] originalbyte)
        {
            if (originalbyte != null && originalbyte.Length >= 16)
            {
                byte[] bytes = new byte[0];
                if (originalbyte.Length == 15) bytes = originalbyte;
                if (originalbyte.Length < 15) return 0;
                if (originalbyte.Length > 15)
                {
                    var str = Encoding.ASCII.GetString(originalbyte).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    if (str.Length > 1)
                    {
                        int count = 0;
                        for (int i = str.Length - 1; i > 0; i--)
                        {
                            if (str[i].Length == 13 && str[i].Contains("WT,+"))
                            {
                                count = i;
                                break;
                            }
                        }
                        bytes = Encoding.ASCII.GetBytes(str[count]);
                    }
                    else
                    {
                        bytes = Encoding.ASCII.GetBytes(str[0]);
                        if (bytes.Length < 15) return null;
                    }
                }
                var section1 = Encoding.ASCII.GetString(bytes, 0, 2);//WT
                var section3 = Encoding.ASCII.GetString(bytes, 3, 1);//+
                var section4 = Encoding.ASCII.GetString(bytes, 4, 7);//value
                double.TryParse(section4, out double w);
                if (section1.ToUpper() == "WT" && section3.Contains("+")) return w;
            }
            return null;
        }

        /// <summary>
        /// 前称重判定
        /// </summary>
        /// <param name="value">称重重量</param>
        /// <param name="pcg">重量对象参数</param>
        /// <returns></returns>
        public static (NGType, double) JudgmentBeforeWeighing(this double value, WeighingParameterModel pcg)
        {
            double weigh = pcg.WeighBeforeFilling;
            double up = Math.Round(pcg.FluctuationWeighBeforeFilling + weigh, 2, MidpointRounding.AwayFromZero);
            double low = Math.Round(weigh - pcg.FluctuationWeighBeforeFilling, 2, MidpointRounding.AwayFromZero);
            return value switch
            {
                var k when k <= up && k >= low => (NGType.合格, 0),
                var k when k > up => (NGType.前称重偏重, value - weigh),
                var k when k < low => (NGType.前称重偏轻, weigh - value),
                _ => (NGType.称重NG, 0),
            };
        }

        /// <summary>
        /// 后称重判定
        /// </summary>
        /// <param name="value">称重重量</param>
        /// <param name="injectionVolume">注液量</param>
        /// <param name="pcg">重量对象参数</param>
        /// <returns></returns>
        public static (NGType, double) JudgmentAfterWeighing(this double value, double injectionVolume, WeighingParameterModel pcg)
        {
            double weigh = pcg.WeighAfterFilling;
            var AfWtLow = Math.Round(weigh - pcg.FluctuationWeighAfterFilling, 2, MidpointRounding.AwayFromZero);
            var AfWtUp = Math.Round(weigh + pcg.FluctuationWeighAfterFilling, 2, MidpointRounding.AwayFromZero);
            var injUp = Math.Round(pcg.InjectionVolume + pcg.FluctuationInjectionVolume, 2, MidpointRounding.AwayFromZero);
            var injLow = Math.Round(pcg.InjectionVolume - pcg.FluctuationInjectionVolume, 2, MidpointRounding.AwayFromZero);
            return (value, injectionVolume) switch
            {
                var k when k.value <= AfWtUp && k.value >= AfWtLow && k.injectionVolume <= injUp && k.injectionVolume >= injLow => (NGType.合格, 0),
                var k when k.value > AfWtUp => (NGType.总量偏重, value - pcg.WeighAfterFilling),
                var k when k.value < AfWtLow => (NGType.总量偏轻, pcg.WeighAfterFilling - value),
                var k when k.injectionVolume > injUp => (NGType.注液偏多, injectionVolume - pcg.InjectionVolume),
                var k when k.injectionVolume < injLow => (NGType.注液偏少, pcg.InjectionVolume - injectionVolume),
                _ => (NGType.称重NG, 0),
            };
        }
    }
}
